package com.hean.util;

import java.io.File;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.content.Context;
import android.util.Log;

public class FileDownloader {
	private Context context;
	private FileService fileService;
	
	private static final String TAG="FileDownloader";
	/*已下载文件大小*/
	private int downloadSize=0;
	/*原始文件大小*/
	private int fileSize=0;
	/*线程数*/
	private DownloadThread[] threads;
	/*下载路径*/
	private URL url;
	/*本地保存文件*/
	private File saveFile;
	/*下载记录文件*/
	private File logFile;
	/*缓存各线程最后下载的位置*/
	private Map<Integer, Integer> data=new ConcurrentHashMap<Integer, Integer>();
	/*每条线程下载的大小*/
	private int block;
	/*下载路径*/
	private String downloadUrl;
	/**
	 * 获取线程数
	 */
	public int getThreadSize(){
		return threads.length;
	}
	public int getFileSize(){
		return fileSize;
	}
	/**
	 * 累计已下载大小
	 * @param size
	 */
	protected synchronized void append(int size){
		downloadSize+=size;
	}
	/**
	 * 更新指定线程最后下载的位置
	 * @param threadId
	 * @param pos
	 */
	protected void update(int threadId,int pos){
		this.data.put(threadId, pos);
	}
	protected synchronized void saveLogFile() {
		this.fileService.update(this.downloadUrl,this.data);
	}
	/**
	 * @param context
	 * @param downloadUrl
	 * @param fileSaveDir
	 * @param threadNum
	 */
	public FileDownloader(Context context,String downloadUrl,File fileSaveDir,int threadNum){
		try {
			this.context=context;
			this.downloadUrl=downloadUrl;
			fileService=new FileService(context);
			this.url=new URL(downloadUrl);
			if(!fileSaveDir.exists())
				fileSaveDir.mkdirs();
			this.threads=new DownloadThread[threadNum];
			HttpURLConnection con=(HttpURLConnection) url.openConnection();
			con.setConnectTimeout(6000);
			con.setRequestMethod("GET");
			con.setRequestProperty("Accept", "image/*");
			con.setRequestProperty("Accept-Language", "zh-CN");
			con.setRequestProperty("Referer", downloadUrl);
			con.setRequestProperty("Charset", "UTF-8");
			con.setRequestProperty("User-Agent", "....");
			con.setRequestProperty("Connection", "Keep-Alive");
			con.connect();
			//TODO
//			printResponseHeader(con);
			if(con.getResponseCode()==200){
				fileSize=con.getContentLength();
				if(fileSize<=0)
					throw new RuntimeException("无法获知文件大小");
				String filename=getFileName(con);
				saveFile=new File(fileSaveDir, filename);
				Map<Integer, Integer> logdata=fileService.getData(downloadUrl);
				if(logdata.size()>0){
					data.putAll(logdata);
				}
				block=fileSize/threads.length+1;
				if(data.size()==threads.length){
					for (int i = 0; i < threads.length; i++) {
						downloadSize+=data.get(i+1)-block*i;
					}
					print("已经下载的长度"+downloadSize);
				}
			}else {
				throw new RuntimeException("服务器响应错误");
			}
		} catch (Exception e) {
			print(e.toString());
			throw new RuntimeException("连接不到下载路径");
		}
	}
	/**
	 * 获取文件名
	 */
	private String getFileName(HttpURLConnection con){
		String filename=url.toString().substring(url.toString().lastIndexOf('/')+1);
		if(filename==null||"".equals(filename.trim())){
			for (int i = 0; ; i++) {
				String mine=con.getHeaderField(i);
				if(mine==null)
					break;
				if("content-disposition".equals(con.getHeaderFieldKey(i).toLowerCase())){
					Matcher m=Pattern.compile(".*filename=(.*)").matcher(mine.toLowerCase());
					if(m.find())
						return m.group(1);
				}
			}
			filename=UUID.randomUUID()+".tmp";//默认取一个文件名
		}
		return filename;
	}
	/**
	 * 开始下载文件
	 * 监听下载数量的变化，如果不需要了解实时下载的数量，可以设置为null
	 * @return 已下载文件的大小
	 */
	public int download(DownloadProgressListener listener) throws Exception{
		try {
			if(data.size()!=threads.length){
				data.clear();
				for (int i = 0; i < threads.length; i++) {
					data.put(i+1, block*i);
				}
			}
			for (int i = 0; i < threads.length; i++) {
				int downLength=data.get(i+1)-block*i;
				if(downLength<block&&data.get(i+1)<fileSize){//该线程未完成下载，继续下载
					RandomAccessFile randOut=new RandomAccessFile(saveFile, "rw");
					if(fileSize>0)
						randOut.setLength(fileSize);
					randOut.seek(data.get(i+1));
					threads[i]=new DownloadThread(randOut,url,block,data.get(i+1),i,downLength,this);
					threads[i].setPriority(7);
					threads[i].start();
				}else{
					threads=null;
				}
			}
			fileService.save(downloadUrl, data);
			boolean notFinish=true;
			while(notFinish){//循环判断是否下载完毕
				Thread.sleep(900);
				notFinish=false;//假定下载完毕
				for (int i = 0; i < threads.length; i++) {
					if(threads[i]!=null&&threads[i].isFinish()){
						notFinish=true;
						if(threads[i].getDownLength()==-1){//如果下载失败，再重新下载
							RandomAccessFile randOut=new RandomAccessFile(saveFile, "rw");
							randOut.seek(data.get(i+1));
							int downLength=data.get(i+1)-block*i;
							threads[i]=new DownloadThread(randOut,url,block,data.get(i+1),i,downLength,this);
							threads[i].setPriority(7);
							threads[i].start();
						}
					}
				}
				if(listener!=null)
					listener.onDownloadSize(downloadSize);
			}
			fileService.delete(downloadUrl);
			return downloadSize;
		} catch (Exception e) {
			print(e.toString());
			throw new RuntimeException("下载失败");
		}
	}
	
	private static void print(String msg){
		Log.i(TAG, msg);
	}
	
	/**
	 * 获取Http响应头字段
	 */
	
}
